package NG::Chat::Client::Interactive;
use strict;
use warnings;
use utf8;

use EV;
use Data::Dumper;
use NG::Sys::Datetime;
use NG::Sys::Text qw(generate_phrase);

use base 'NG::Chat::Client::Handler';


sub new {
	my $class = shift;
	my $self = $class->SUPER::new(@_);

	$self->{input} = EV::io(\*STDIN, EV::READ, input_handler($self->{client}));

	$self->{signal} = EV::signal( 'INT', sub {
		EV::break EV::BREAK_ALL;
		print "\nGot signal INT\n";
	});
	return $self;
}
sub cleanup {
	my $self = shift;
	$self->SUPER::cleanup;
	delete $self->{input};
	delete $self->{signal};
}

sub input_handler {
	my $client = shift;
	return sub {
		my $str = <STDIN>;
		$str =~ s/\s+$//;
		if(my $msg = parse_input($str)){
			if($msg->{cmd} eq "flood"){
				run_flood($client,$msg);
				print "flood run\n";
			}
			elsif(my $err = $client->send_message($msg)){
				print "ERROR: $err->{text}\n";
			}
		}
	};
}

sub parse_input {
	my $str = shift;
	my $msg;
	unless($str){
		return;
	}elsif($str =~ s/^\/(\w+)//){
		$msg = { cmd =>  $1 };
		for(map {s/\\(\s)/$1/g;$_} split /(?:(?<!\\)\s)+/,$str){
			my ($k,$v) = map {s/^\s+//;s/\s+$//;$_} split /:/,$_,2;
			#print "k='$k' v='$v'\n";
			next unless $k;
			unless(defined($v) and $v ne ""){
				print "input error: odd param\n";
				return;
			}
			$msg->{$k} = $v;
		}
	}else{
		$msg = {
			cmd => "message",
		};
		if($str =~ s/!(\w+)//){
			$msg->{chanel} = $1;
		}
		$msg->{text} = $str;
	}
	return $msg;
}
sub process_response {
	my $client = shift;
	my $msg = shift;
	if($msg->{type} && $msg->{type} eq "list"){
		print "LISTSIZE=",scalar(@{$msg->{list}})," rid=$msg->{rid}\n";
		for(sort {$a->{ats} <=> $b->{ats}} @{$msg->{list}}){
			process_one_response($client,$_);
		}
		return 1;
	}else{
		return process_one_response($client,$msg);
	}
}
sub process_one_response {
	my $client = shift;
	my $msg = shift;
	unless($msg->{type}){
		print Dumper($msg);
	}elsif($msg->{type} eq "response"){
		if($msg->{error}){
			if($msg->{error} == 401){
				$client->{sid} = "";
			}
			print unixtime2hms($msg->{ats})." RESPONSE($msg->{command}:$msg->{rid}): error($msg->{error}): ",$msg->{text},"\n";
		}else{
			print unixtime2hms($msg->{ats})." RESPONSE($msg->{command}:$msg->{rid}): ",$msg->{text},"\n" if $msg->{text};
		}
	}
	elsif($msg->{type} eq "message"){
		print unixtime2hms(),"<",($_->{chanel}||""),"> ",unixtime2hms($msg->{ats})," [",($msg->{from}||""),":",($msg->{rid}||""),"] ",$msg->{text},"\n";
	}
	elsif($msg->{type} eq "notice"){
		if($msg->{param1} eq "welcome"){
			$client->{sid} = $msg->{sid};
			$client->{login} = $msg->{param3};
			$client->{chanel} = $msg->{chanel};
			print "auth: joined to '$msg->{chanel}'\n";
			return 1;
		}
		elsif($msg->{param1} eq "join" && $msg->{param2} eq $client->{login}){
			print "joined: $msg->{chanel}\n";
		}
		else{
			print unixtime2hms(),"<",($msg->{chanel}||""),"> ",unixtime2hms($msg->{ats})," notice(",($msg->{level}||""),"): "
				,($msg->{param1}||"")," | "
				,($msg->{param2}||"")," | "
				,($msg->{param3}||"")," | "
				,($msg->{text}||"")
				,"\n";
		}
	}else{
		print Dumper($msg);
	}
	return 0;
}
sub run_flood {
	my $client = shift;
	my $msg = shift;
	my $to = $msg->{to} || 5;
	my $w = EV::timer $to,$to,\&send_flood;
	my $data = {
		w => $w,
		cl => $client,
		c => 0,
		mc => $msg->{mc} || ~1,
		wl => ($msg->{wl}?[split /,/,$msg->{wl}]:undef),
		wc => ($msg->{wc}?[split /,/,$msg->{wc}]:undef),
		cn => $msg->{cn},
	};
	$w->data($data);
}
sub send_flood {
	my $w = shift;
	if(++$w->data->{c} > $w->data->{mc}){
		delete $w->data->{cl};
		delete $w->data->{w};
		delete $w->data->{wc};
		delete $w->data->{wl};
		$w->stop;
		return;
	}
	my $msg = {
		cmd => "message",
		text => generate_phrase($w->data->{wl},$w->data->{wc}),
		chanel => $w->data->{cn},
	};
	$w->data->{cl}->send_message($msg);
}
1;
